package com.gitee.dupe.file.strategy.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.gitee.dolt.core.exception.code.ExceptionCode;
import com.gitee.dolt.core.util.BizAssert;
import com.gitee.dolt.utils.DateUtils;
import com.gitee.dolt.utils.FileTypeUtils;
import com.gitee.dolt.utils.VideoUtils;
import com.gitee.dolt.utils.web.ResponseUtils;
import com.gitee.dupe.common.properties.DupeProperties;
import com.gitee.dupe.file.entity.Attachment;
import com.gitee.dupe.file.utils.ConvertVideoUtils;
import it.sauronsoftware.jave.MultimediaInfo;
import it.sauronsoftware.jave.VideoInfo;
import it.sauronsoftware.jave.VideoSize;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author LYH
 */
@RequiredArgsConstructor
@Slf4j
public class LocalFileStrategyImpl extends AbstractFileStrategy {

    private final DupeProperties dupeProperties;

    @Override
    protected void uploadFile(Attachment attachment, MultipartFile multipartFile) {
        DupeProperties.FileProperties fileProperties = dupeProperties.getFile();
        // 生成文件名
        String fileName = IdUtil.simpleUUID() + StrUtil.DOT + attachment.getExt();

        // 日期文件夹
        String relativeDoc = Paths.get(LocalDate.now().format(DateTimeFormatter.ofPattern(DateUtils.DEFAULT_MONTH_FORMAT_SLASH))).toString();
        // web服务器存放的绝对文件夹
        String absoluteDoc = Paths.get(fileProperties.getUploadPath(), relativeDoc).toString();
        // 文件绝对地址
        String absolutePath = Paths.get(absoluteDoc, fileName).toString();

        try {
            FileUtil.writeBytes(multipartFile.getBytes(), absolutePath);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            BizAssert.fail(ExceptionCode.BAD_REQUEST.getCode(), "文件上传失败");
        }

//        boolean videoConvert = false;
//        MultimediaInfo multimediaInfo = VideoUtils.getMultimediaInfo(absolutePath);
//        if (multimediaInfo != null) {
//            VideoInfo videoInfo = multimediaInfo.getVideo();
//            String decoder = videoInfo == null ? null : videoInfo.getDecoder();
//            // 视频编码
//            if (!"h264".equals(decoder)) {
//                String targetFilePath = Paths.get(absoluteDoc, IdUtil.simpleUUID() + ".mp4").toString();
//                targetFilePath = ConvertVideoUtils.convert(absolutePath, targetFilePath);
//                if (StrUtil.isNotEmpty(targetFilePath)) {
//                    FileUtil.del(absolutePath);
//                    absolutePath = targetFilePath;
//                    fileName = FileUtil.getName(targetFilePath);
//                    videoConvert = true;
//                }
//            }
//        }
//        if (videoConvert) {
//            multimediaInfo = VideoUtils.getMultimediaInfo(absolutePath);
//        }

        Long duration = null;
        String size2 = null;
        if (FileTypeUtils.isVideo(FileUtil.file(absolutePath))) {
            String targetFilePath = Paths.get(absoluteDoc, IdUtil.simpleUUID() + ".mp4").toString();
            targetFilePath = ConvertVideoUtils.convert(absolutePath, targetFilePath);
            FileUtil.del(absolutePath);
            absolutePath = targetFilePath;
            fileName = FileUtil.getName(targetFilePath);
            MultimediaInfo multimediaInfo = VideoUtils.getMultimediaInfo(absolutePath);

            if (multimediaInfo != null) {
                VideoInfo videoInfo = multimediaInfo.getVideo();
                duration = multimediaInfo.getDuration();
                if (videoInfo != null) {
                    VideoSize videoSize = videoInfo.getSize();
                    if (videoSize != null) {
                        size2 = videoSize.getWidth() + "*" + videoSize.getHeight();
                    }
                }
            }
        }

        String relativePath = relativeDoc + StrUtil.SLASH + fileName;
        String uriPrefix = fileProperties.getUriPrefix();
        //替换掉windows环境的\路径
        relativePath = StrUtil.replace(relativePath, "\\\\", StrUtil.SLASH);
        relativePath = StrUtil.replace(relativePath, "\\", StrUtil.SLASH);

        if (!StrUtil.endWith(uriPrefix, StrUtil.SLASH)) {
            uriPrefix = uriPrefix + StrUtil.SLASH;
        }

        String url = uriPrefix + relativePath;
        attachment.setUrl(url);
        attachment.setUri(relativePath);
        attachment.setFilename(fileName);
        attachment.setRelativePath(relativePath);
        attachment.setAbsolutePath(absolutePath);

        attachment.setDuration(duration);
        attachment.setSize2(size2);

    }

    @Override
    public void download(HttpServletRequest request, HttpServletResponse response, List<Attachment> attachments) {
        DupeProperties.FileProperties fileProperties = dupeProperties.getFile();
        List<Attachment> usedAttachments = attachments.stream().filter(e -> FileUtil.exist(e.getAbsolutePath()))
                .collect(Collectors.toList());
        BizAssert.isTrue(!usedAttachments.isEmpty(), "文件不存在");
        if (usedAttachments.size() == 1) {
            Attachment attachment = usedAttachments.get(0);
            ResponseUtils.renderFile(response, FileUtil.file(attachment.getAbsolutePath()), attachment.getSubmittedFileName());
            return;
        }
        File file = Paths.get(fileProperties.getTempPath(), IdUtil.simpleUUID() + ".zip").toFile();
        List<File> usedFiles = usedAttachments.stream().map(e -> FileUtil.file(e.getAbsolutePath())).collect(Collectors.toList());
        ZipUtil.zip(file, false, ArrayUtil.toArray(usedFiles, File.class));
        ResponseUtils.renderFile(response, file);
        FileUtil.del(file);
    }

    @Override
    public void delete(List<Attachment> attachments) {
        attachments.forEach(e -> {
            FileUtil.del(Paths.get(e.getAbsolutePath(), e.getFilename()));
        });
    }
}
